import Foundation
import UIKit

// 图片控件回调
protocol PictureCtrlCallback: NSObjectProtocol {
    func movePicture(_ pictureCtrl: PictureCtrl)   // 图片控件的单击事件
}

// 图片控件
class PictureCtrl: UIView {
    private var mCallback: PictureCtrlCallback! // 回调
    private var mHasBorder: Bool!               // 有边框则为 true，否则为 false
    private var mImage: CGImage!                // 图片
    private var mOriginalPosition: CGPoint!     // 原位置，即刚被创建时的初始位置

    /**
     * 构造方法。
     * @param callback  回调
     * @param hasBorder 有边框则为 true，否则为 false
     * @param image     图片
     * @param parent    父窗口
     * @param rect      位置、尺寸
     */
    public init(_ callback: PictureCtrlCallback, hasBorder: Bool, image: CGImage, parent: UIView, rect: CGRect) {
        // 初始化成员
        mCallback = callback
        mHasBorder = hasBorder
        mImage = image.cropping(to: rect)!
        mOriginalPosition = rect.origin
        super.init(frame: rect)

        // 添加到父窗口上
        parent.addSubview(self)

        // 添加手势事件监听者
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapGestureAction))
        tapGesture.numberOfTapsRequired = 1
        super.addGestureRecognizer(tapGesture)

        // 重绘
        super.setNeedsDisplay()
    }

    /**
     * 必要的构造方法。
     * @param coder 解码器
     */
    public required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    /**
     * 重绘事件的响应方法。
     * @param rect  要重绘的区域
     */
    public override func draw(_ rect: CGRect) {
        let drawer = UIGraphicsGetCurrentContext()!
        drawer.saveGState()
        drawer.translateBy(x: 0, y: bounds.width)
        drawer.scaleBy(x: 1, y: -1)
        drawer.draw(mImage, in: rect)
        drawer.restoreGState()
        if mHasBorder {
            self.drawEdge(drawer)
        }
    }

    /**
     * 绘制边框。
     * @param drawer    绘图者
     */
    private func drawEdge(_ drawer: CGContext) {
        let left = CGFloat(0)
        let top = CGFloat(0)
        let right = left + frame.width - 1
        let bottom = top + frame.height - 1
        var rect: CGRect!
        
        drawer.setFillColor(Const.colorLeftTop1)
        rect = CGRect(x: left, y: top, width: frame.width - 1, height: 1)
        drawer.fill(rect)
        rect = CGRect(x: left, y: top, width: 1, height: frame.height - 1)
        drawer.fill(rect)
        
        drawer.setFillColor(Const.colorLeftTop2)
        rect = CGRect(x: left + 1, y: top + 1, width: frame.width - 3, height: 1)
        drawer.fill(rect)
        rect = CGRect(x: left + 1, y: top + 1, width: 1, height: frame.height - 3)
        drawer.fill(rect)

        drawer.setFillColor(Const.colorRightBottom1)
        rect = CGRect(x: right, y: top, width: 1, height: frame.height)
        drawer.fill(rect)
        rect = CGRect(x: left, y: bottom, width: frame.width - 1, height: 1)
        drawer.fill(rect)

        drawer.setFillColor(Const.colorRightBottom2)
        rect = CGRect(x: right - 1, y: top + 1, width: 1, height: frame.height - 2)
        drawer.fill(rect)
        rect = CGRect(x: left + 1, y: bottom - 1, width: frame.width - 3, height: 1)
        drawer.fill(rect)
    }

    /**
     * 获取/设置边框。
     */
    public var hasBorder: Bool {
        get {
            return mHasBorder
        } set {
            if mHasBorder == newValue {
                return
            }
            mHasBorder = newValue
            super.setNeedsDisplay()
        }
    }

    /**
     * 判断自身是否在初始位置。
     * @return 在初始位置则返回 true，否则返回 false
     */
    public func isOnOriginalPosition() -> Bool {
        return frame.origin.x == mOriginalPosition.x && frame.origin.y == mOriginalPosition.y
    }

    /**
     * 单击事件的响应方法。
     */
    @objc private func tapGestureAction() {
        mCallback.movePicture(self)
    }
}
